#ifndef DUAL_GRAPH_H
#define DUAL_GRAPH_H

#include <math.h>
#include <assert.h>

#include "../sdf/dynarray.h"
#include "cut.h"
#include "dct_node.h"

namespace PBVP {
	/// Dual Contour Tree (DCT) class
	/**
	* 
	*/
	class DualGraph {
	public:
		///Construct a new dual contour tree
		/**
		* @param nr: The number of functional ranges
		* @param min: The minimum value of functional range
		* @param max: Tha maximum value of functional range
		*/ 
		DualGraph(float min = 0, float max = 1, int nr = 1); 

		/// Destructor
		~DualGraph();

		///	Get the number of ranges
		int numOfRanges() const {
			return n_Ranges;
		}

		///	Construct a new dual graph by merging two adjacent subranges
		DualGraph* mergeRanges();

		///	Print out info about the dual graph
		void print();

		///	get the nth node in the level lvl
		DualNode* getNode(int lvl, int n) {
			return (nodes[lvl])[n];
		}

		///	Get the total number of all nodes in the dual tree
		int totalNodes() const {
			return nnodes;
		}

		/// Get the number of nodes in the range i
		int numOfNodes(int i) const {
			return nodes[i].size();
		}

		///	Save the dual graph into a file
		void saveFile(const char* fname);

		/// Load a dual graph from a file
		/**
		* @param fname
		* 
		* @return DualGraph*: NULL if loading failed
		*/
		bool loadFile(const char* fname);

		///  Add a node to level i.
		void addDNote(int r, DualNode* p_dnode) {
#ifdef _DEBUG
			assert(r < n_Ranges);
#endif
			nodes[r].insert(p_dnode);
		}

		/// Accessor to node j and level i.
		DualNode*& node(int r, int nid) {
#ifdef _DEBUG
			assert(r < n_Ranges);
#endif		
			return nodes[r][nid];
		}

		/// Set the range of dual contour tree	
		void setRange(float min, float max) {
			m_min = min;
			m_max = max;
		}

		/// Remove nodes with volume < threshold
		void prune(float threshold);

		/// Insert a node to the level l of the tree
		void insert(int l, DualNode* pnode) {
			nodes[l].insert(pnode);
			nnodes ++;
		}

		/// Convert DCTree info to a QString
		QString toQString() const;

		/// xiaoyu 4/3/08
		//float getTotalVolume() const {
		//	return data->getVolume();
		//}
	protected:
		friend class DCTConstructor;

		float 	m_min, m_max;
		int		n_Ranges;					// number of functional ranges
		int		nnodes;						// number of dual nodes
		float	*cut_vals;					// range cutting values
		dynamic_array<DualNode*> *nodes;	// Arrays of dual tree nodes
		dynamic_array<DualNode*> pruned;

	private:
		friend class MultiConTree;

		/// Release all memory
		void clean();
	};
}
#endif

